﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Net;
using System.Xml;

namespace AnaViewer
{
    /// <summary>
    /// 表示 RSS 2.0 XML 文档中的一个 RSS 元素。
    /// </summary>
    public class RssSource : ISource
    {
        private string title= "";
        private string link = "";
        private string desc = "";
        public string Title { get { return title; } }
        public string Link { get { return link; } }
        public string Description { get { return desc; } }

        /// <summary>
        /// 以工厂模式使用的私有构造函数。
        /// </summary>
        /// <param name="xmlNode">一个包含 RSSFeed 内容的 XML 块。</param>
        public RssSource()
            : base()
        {
        }

        protected string anaUrl = "";
        public string AnaUrl
        {
            get { return anaUrl; }
            set { anaUrl = value; }
        }


        private IList<IItem> Load(XmlNode xmlNode)
        {
            if (xmlNode == null)
                return null;
            // 读取 <rss> 标记
            XmlNode rssNode = xmlNode.SelectSingleNode("rss");
            if (rssNode == null)
                return null;

            //仅仅使用第一个通道
            XmlNode channelNode = rssNode.SelectSingleNode("channel");
            if (channelNode == null)
                return null;
            else
            {
                List<IItem> items = new List<IItem>();
                XmlNode node =channelNode.SelectSingleNode("title");
                if (node != null)
                    title = node.InnerText;
                node = channelNode.SelectSingleNode("link");
                if (node != null)
                    link = node.InnerText;
                node = channelNode.SelectSingleNode("description");
                if (node != null)
                    desc = node.InnerText;

                XmlNodeList itemNodes = channelNode.SelectNodes("item");
                foreach (XmlNode itemNode in itemNodes)
                {
                    items.Add(new RssItem(itemNode));
                }

                return items.AsReadOnly();
            }
        }

        #region IAnaSource 成员

        public IList<IItem> LoadUri(string uri)
        {
            IList<IItem> items = null;
            try
            {
                XmlDocument xmlDoc;
                WebClient webClient = new WebClient();
                using (Stream rssStream = webClient.OpenRead(uri))
                {
                    TextReader textReader = new StreamReader(rssStream);
                    XmlTextReader reader = new XmlTextReader(textReader);
                    xmlDoc = new XmlDocument();
                    xmlDoc.Load(reader);
                }
                items = this.Load(xmlDoc);
            }
            catch
            {
                items = null;
            }

            return items;
        }
        public IList<IItem> LoadXml(string rssText)
        {
            IList<IItem> items = null;
            try
            {
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.LoadXml(rssText);
                items = this.Load(xmlDoc);
            }
            catch
            {
                items = null;
            }

            return items;
        }

        public IList<IItem> ReLoad()
        {
            if (anaUrl == null || anaUrl == "")
                return null;

            return LoadUri(anaUrl);
        }


        /// <summary>
        /// 验证指定路径是否是有效的 Ana 源。
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static bool Validate(string anaUrl)
        {
            bool result = false;
            try
            {
                RssSource source = new RssSource();
                if( source.LoadUri(anaUrl) == null)
                    result = false;
                else
                    result = true;
            }
            catch
            {
                result = false;
            }
            return result;
        }

        #endregion

    }
}
